
package com.studiofortress.sf.audio;

import java.io.IOException;
import java.io.InputStream;

/**
 *
 * @author Joseph Lenton - JosephLenton@StudioFortress.com
 */
class CachingInputStream extends InputStream
{
    private final AudioBuffer buffer;
    private int index;
    private int mark;
    
    public CachingInputStream(AudioBuffer buffer)
    {
        this.buffer = buffer;
        index = 0;
        mark = index;
    }

    private static final int unsigned(byte b)
    {
        return b & 0xFF;
    }

    /**
     * Unsupported.
     * @return
     * @throws IOException
     */
    @Override
    public int read() throws IOException
    {
        if (available() > 0) {
            return unsigned( buffer.getByte(index++) );
        } else {
            return -1;
        }
    }

    @Override
    public int available() throws IOException
    {
        int available = buffer.size()-index;
        
        while (available == 0 && !buffer.isFinished()) {
            Thread.yield();
            available = buffer.size()-index;
        }
        
        return available;
    }

    @Override
    public void close() throws IOException
    {
    }

    @Override
    public synchronized int read(byte[] b) throws IOException
    {
        if (available() > 0) {
            final int copySize = Math.min(b.length, buffer.size()-index);

            System.arraycopy( buffer.getBuffer(index, copySize), 0, b, 0, copySize );
            index += copySize;

            return copySize;
        } else {
            return -1;
        }
    }
    
    @Override
    public boolean markSupported()
    {
        return true;
    }
    
    @Override
    public synchronized void mark(int readlimit)
    {
        mark = index;
    }

    /**
     *
     * @throws IOException
     */
    @Override
    public synchronized void reset() throws IOException
    {
        index = mark;
    }

    @Override
    public synchronized int read(byte[] b, int off, int len) throws IOException
    {
        if (available() > 0) {
            final int copySize = Math.min(len, buffer.size()-index);

            System.arraycopy( buffer.getBuffer(index, copySize), 0, b, off, copySize );
            index += copySize;

            return copySize;
        } else {
            return -1;
        }
    }

    /**
     * This method is not supported.
     * @param n
     * @return
     * @throws IOException
     */
    @Override
    public long skip(long n) throws IOException
    {
        index += (int) n;
        return n;
    }
}
